<?php
declare (strict_types=1);

namespace app\common\model;

use addons\Pay\facade\Pay;
use addons\Target\facade\Target;
use app\common\controller\Bonus;
use think\facade\Cache;
use think\facade\Event;
use think\helper\Str;

class OrderTemporary extends Order
{
    public static function setTemporary($param, $user): array
    {
        try {
            if (empty($user->parent_id) && $user->id != 1) {
                return ['code' => 205, 'msg' => '请您先完善推荐人信息'];
            }
            if (empty($user->pay_password)) {
                return ['code' => 204, 'msg' => '请您先完善支付密码'];
            }
            if ($param['type'] == 1) {
                $result = ProductSpec::getSettled($param, $user);
            } else {
                $result = ProductCart::getSettled($param['cart_id'], $user);
            }
            if ($result['code'] != 1) {
                throw new \Exception($result['msg']);
            }
            $productTemporary = $result['data'];
            if (empty($productTemporary)) {
                throw new \Exception('服务器错误，请稍后再试');
            }
            Cache::delete('productTemporaryCartId_' . $user->id);
            //缓存购物车标识
            if (!empty($param['cart_id'])) {
                Cache::set('productTemporaryCartId_' . $user->id, $param['cart_id']);
            }
            Cache::set('productTemporary_' . $user->id, $productTemporary);

            return ['code' => 1, 'msg' => 'success'];
        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function getTemporary($uid): array
    {
        try {
            $temporary = Cache::get('productTemporary_' . $uid);
            if (empty($temporary)) {
                throw new \Exception('加载失败，请再试一次！');
            }
            $temporary['address'] = Address::getDefault($uid);

            return ['code' => 1, 'msg' => 'success', 'data' => $temporary];
        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function submit($param, $user): array
    {
        try {
            $temporary = Cache::get('productTemporary_' . $user->id);
            if (empty($temporary)) {
                throw new \Exception('加载失败，请再试一次！');
            }
            if (empty($param['address_id'])) {
                throw new \Exception('请选择收货地址');
            }
            $address = Address::where(['id' => $param['address_id'], 'uid' => $user->id])->find();
            if (empty($address)) {
                throw new \Exception('收货地址错误，请重新选择');
            }
            $param['product'] = $temporary['product'];

            return self::createOrder($param, $user, $address);
        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function createOrder($param, $user, $address): array
    {
        $time = time();
        $order_type = $num = $amount = $freight = 0;
        foreach ($param['product'] as &$children) {
            $product = Product::where(['id' => $children['pid'], 'status' => 1])->find();
            if (empty($product)) {
                return ['code' => -1, 'msg' => "商品《{$product->title}》已下架"];
            }
            if ($product->spec_open == 2) {
                $specValue = ProductSpec::where(['pid' => $children['pid'], 'merge_title' => $children['spec']])->find();
                if (empty($specValue) || $children['num'] > $specValue->stock) {
                    return ['code' => -1, 'msg' => "'商品《{$product->title}-{$children['spec']}》库存不足'"];
                }
                $children['icon'] = $specValue->icon ?: $product->icon;
                $children['vip_price'] = $specValue->vip_price;
                //减少库存
                $specValue->stock -= $children['num'];
                $specValue->save();
            } else {
                if ($children['num'] > $product->stock) {
                    return ['code' => -1, 'msg' => "商品《{$product->title}》库存不足"];
                }
                $children['icon'] = $product->icon;
                $children['vip_price'] = $product->vip_price;
            }
            $children['amount'] = round($children['vip_price'] * $children['num'], 2);
            $num += $children['num'];
            //订单总价格
            $amount += $children['amount'];
            $freight += $children['freight'];
            //增加销量
            $product->sales += $children['num'];
            $product->stock -= $children['num'];
            $product->save();
            //定义订单类别
            $order_type = $product->type_id;
        }
        parent::startTrans();
        try {
            $new = parent::create([
                'sn' => 'T' . date('YmdHis') . Str::random(6, 1) . $user->id,
                'uid' => $user->id,
                'order_type' => $order_type,
                'num' => $num,
                'total_amount' => $amount,
                'freight' => $freight,
                'real_amount' => round($amount + $freight, 2),
                'address_id' => !empty($address) ? $address->id : 0,
                'receiver' => !empty($address) ? $address->nickname : '',
                'receiver_tel' => !empty($address) ? $address->tel : '',
                'province' => !empty($address) ? $address->province : '',
                'city' => !empty($address) ? $address->city : '',
                'district' => !empty($address) ? $address->district : '',
                'address_details' => !empty($address) ? $address->details : '',
                'remark' => !empty($param['remark']) ? $param['remark'] : '',
                'status' => 1,
                'expire_time' => round(Cache::get('system')['payment_timeout'] * 60 + $time)
            ]);
            $walk = ['order_id' => $new->id, 'uid' => $user->id, 'create_time' => $time, 'update_time' => $time];
            array_walk($param['product'], function (&$value, $key, $walk) {
                $value = array_merge($value, $walk);
            }, $walk);
            (new OrderProduct())->insertAll($param['product']);
            $cart_id = Cache::get('productTemporaryCartId_' . $user->id);
            if ($cart_id) {
                ProductCart::destroy(['id' => $cart_id], true);
                Cache::delete('productTemporaryCartId_' . $user->id);
            }
            Cache::delete('productTemporary_' . $user->id);
            parent::commit();

            return ['code' => 1, 'msg' => '订单已生成', 'data' => ['order_id' => $new->id]];
        } catch (\Exception $e) {
            parent::rollback();

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function replaceAddress($param, $user): array
    {
        try {
            $info = parent::where(['id' => $param['id'], 'uid' => $user->id])->find();
            if (empty($info)) {
                throw new \Exception('订单不存在或已失效');
            }
            if (!in_array($info->getData('status'), [1, 2])) {
                throw new \Exception('订单已发货或已取消');
            }
            $address = Address::where(['id' => $param['address_id']])->find();
            if (empty($address)) {
                throw new \Exception('新收货地址错误，请重新选择');
            }
            $info->address_id = $address->id;
            $info->receiver = $address->nickname;
            $info->receiver_tel = $address->tel;
            $info->province = $address->province;
            $info->city = $address->city;
            $info->district = $address->district;
            $info->address_details = $address->details;
            $info->save();

            return ['code' => 1, 'msg' => '修改成功'];
        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function getPayment($id, $user): array
    {
        try {
            $info = parent::field('id,sn,order_type,real_amount,expire_time,status')
                ->where(['id' => $id, 'uid' => $user->id])->find();
            if (empty($info)) {
                throw new \Exception('无效订单');
            }
            if ($info->getData('status') != 1) {
                throw new \Exception('订单已支付或已失效');
            }
            $info->surplus_time = round(($info->expire_time - time()) * 1000);
            $data['order'] = $info;
            $data['method'] = self::payWay($info->order_type);

            return ['code' => 1, 'msg' => 'success', 'data' => $data];
        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function payWay($order_type = ''): array
    {
        return match ($order_type) {
            default => self::getPaymentMethod(['currency', 'bonus'])
        };
    }

    public static function getPaymentMethod($data): array
    {
        $method = [];
        foreach ($data as $item) {
            if (in_array($item, ['wechat', 'alipay'])) {
                $is_pay = 0;
                $icon = $item;
            } else {
                $is_pay = 1;
                $icon = 'wallet';
            }
            $method[] = [
                'title' => get_pay_way($item),
                'pay_way' => $item,
                'icon' => "/static/admin/img/{$icon}.png",
                'is_pay_password' => $is_pay
            ];
        }

        return $method;
    }

    public static function payment($param, $user): array
    {
        try {
            $info = parent::where(['id' => $param['id']])->find();
            if ($info->getData('status') != 1) {
                throw new \Exception('订单已支付或已失效');
            }
            $pay_way = $param['pay_way'];
            switch ($pay_way) {
                case "currency":
                case "bonus":
                    if (md5($param['pay_password']) != $user->pay_password) {
                        throw new \Exception('支付密码错误');
                    }
                    if ($info->real_amount > $user->assets->$pay_way) {
                        throw new \Exception(get_pay_way($pay_way) . '账户余额不足');
                    }

                    return self::operations($info, $user, $pay_way);
                case "wechat":
                    $notifyUrl = request()->domain() . '/time/callback/wechatNotice';
                    $options = Pay::setDriver('WeChat')->basic('购买商品', $info->sn, 0.01, $notifyUrl)
                        ->create('MWEB');

                    return ['code' => 1, 'msg' => 'success', 'data' => $options];
                case "alipay":
                    $notifyUrl = request()->domain() . '/time/callback/alipayNotice';
                    $options = Pay::setDriver('AliPay')->basic('购买商品', $info->sn, 0.01, $notifyUrl)
                        ->create('Wap');

                    return ['code' => 1, 'msg' => 'success', 'data' => $options];
                default:
                    throw new \Exception('暂未开放');
            }

        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function operations($info, $user, $pay_way, $transaction_id = ''): array
    {
        parent::startTrans();
        try {
            $info->status = 2;
            $info->pay_state = 1;
            $info->pay_way = $pay_way;
            if (!empty($transaction_id)) {
                $info->transaction_id = $transaction_id;
            }
            $info->pay_time = time();
            $info->save();
            if (!in_array($pay_way, ['wechat', 'alipay'])) {
                Target::Account()->basics($user->id, $pay_way, $info->real_amount, '购买商品', '-')
                    ->createNormal();
            }
            if ($info->order_type == 1) {
                if ($user->is_active == 1) {
                    $user->is_active = 2;
                    $user->active_type = 1;
                    $count = User::where(['parent_id' => $user->parent_id, 'is_active' => 2])->count();
                    $user->active_sort = $count + 1;
                    $user->active_time = time();
                    if ($user->parent_id) {
                        User::where(['id' => $user->parent_id])->inc('push_num')->save();
                        $renewData[] = ['fx' => '+', 'field' => 'team_num', 'num' => 1];
                    }
                    Event::trigger('Statistics', ['key' => 'formal_user', 'value' => 1]);
                }
                $user->my_total += $info->real_amount;
                $user->save();
                $renewData[] = ['fx' => '+', 'field' => 'team_total', 'num' => $info->real_amount];
                Relation::renewTeamTotal($user->id, $renewData);
                $renewNodeData[] = ['fx' => '+', 'field' => 'total', 'num' => $info->real_amount];
                $renewNodeData[] = ['fx' => '+', 'field' => 'surplus', 'num' => $info->real_amount];
                UserNode::renewTeamTotal($user->id, $renewNodeData);
                Bonus::teamBonus($user->id, $info->real_amount);
                Level::upgrade($user->id);
            }
            Event::trigger('Statistics', ['key' => 'income', 'value' => $info->real_amount]);
            parent::commit();

            return ['code' => 1, 'msg' => '支付成功'];
        } catch (\Exception $e) {
            parent::rollback();
            Logs::write('logs/Order-operations.log', "【{$e->getMessage()}】，参数【" . json_encode($info) . "】");

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function edit($param, $user): array
    {
        parent::startTrans();
        try {
            $info = parent::where(['id' => $param['id'], 'uid' => $user->id])->find();
            if (empty($info)) {
                throw new \Exception('此订单不存在');
            }
            switch ($param['type']) {
                case 'cancel': //取消订单
                    if ($info->getData('status') != 1 || $info->pay_state) {
                        throw new \Exception('此订单已支付，无法取消');
                    }
                    self::cancel($info);
                    $msg = '订单取消成功';
                    break;
                case "remind": //提醒发货
                    if ($info->getData('status') != 2) {
                        throw new \Exception('此订单未支付或已发货');
                    }
                    if ($info->is_remind) {
                        throw new \Exception('您已提醒发货了');
                    }
                    $info->is_remind = 1;
                    $info->remind_time = time();
                    $info->save();
                    $msg = '提醒发货成功';
                    break;
                case "receipt": //确认收货
                    if ($info->getData('status') != 3) {
                        throw new \Exception('此订单无需收货');
                    }
                    self::receipt($info);
                    $msg = '确认收货成功';
                    break;
                default:
                    throw new \Exception('操作有误');
            }
            parent::commit();

            return ['code' => 1, 'msg' => $msg];
        } catch (\Exception $e) {
            parent::rollback();

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function cancel($info): bool|string
    {
        try {
            $info->status = 6;
            $info->cancel_time = time();
            $info->save();
            Event::trigger('Operation', $info->id);

            return true;
        } catch (\Exception $e) {

            return $e->getMessage();
        }
    }

    public static function receipt($info, $is_auto = false): bool|string
    {
        try {
            $time = time();
            $info->status = 5;
            $info->receipt_time = $time;
            $info->finish_time = $time;
            if ($is_auto) $info->auto_receipt_time = $time;
            $info->save();
            $content = "您的订单【{$info->sn}】确认收货成功";
            UserNotify::add(2, $info->uid, '订单收货', $content, $info->id);

            return true;
        } catch (\Exception $e) {

            return $e->getMessage();
        }
    }

    /**
     * 订单支付超时自动取消
     * 定时
     */
    public static function autoCancel(): array
    {
        parent::startTrans();
        try {
            parent::where(['status' => 1, 'pay_state' => 0])->where('expire_time', '<', time())->select()->each(function ($item) {
                self::cancel($item);
            });
            parent::commit();

            return ['code' => 1, 'msg' => '执行成功'];
        } catch (\Exception $e) {
            parent::rollback();
            Logs::write('logs/Order-autoCancel.log', $e->getMessage());

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 订单自动确认收货
     * 定时
     */
    public static function autoReceipt(): bool|string
    {
        try {
            parent::where(['status' => 3])->where('auto_receipt_time', '<', time())->select()->each(function ($item) {
                self::receipt($item, true);
            });

            return true;
        } catch (\Exception $e) {

            return $e->getMessage();
        }
    }
}